import re
import csv
from datetime import datetime
import os
import glob
import json

def parse_log_file(file_path):
    # 检查文件是否存在
    if not os.path.exists(file_path):
        print(f"错误：文件 {file_path} 不存在!")
        return []
        
    print(f"开始解析文件: {file_path}")
    
    # 读取文件的所有行
    with open(file_path, 'r', encoding='utf-8', errors='replace') as file:
        lines = file.readlines()
    
    # 手动查找和修复跨行数据
    fixed_lines = []
    i = 0
    fixed_count = 0
    
    while i < len(lines):
        line = lines[i].strip()
        
        # 检查是否是特定的跨行模式
        if "$TPDAT,3,0107,4037,4193,4" in line:
            # 看下一行是否以"173,"开头
            if i + 1 < len(lines) and "173," in lines[i + 1]:
                next_line = lines[i + 1].strip()
                # 构建合并后的行 - 正确提取并替换逗号分隔的数值
                # 分解当前行的各部分
                parts = line.split(',')
                # 确认最后一个部分是4
                if parts[-1] == '4':
                    # 替换最后一个部分为4173
                    parts[-1] = '4173'
                    # 重新组合行，保持原始结构
                    merged_line = ','.join(parts)
                    print(f'修复跨行数据 - 行 {i+1}: 将",4"和"173,"合并为",4173,"')
                    fixed_lines.append(merged_line)
                    fixed_count += 1
                    i += 2  # 跳过下一行
                    continue
        
        # 更一般的处理：检查是否以TPDAT开头且以数字结尾
        if "$TPDAT," in line and re.search(r',(\d+)$', line):
            # 提取末尾的数字
            end_number = re.search(r',(\d+)$', line).group(1)
            
            # 检查下一行是否存在且以数字开头
            if i + 1 < len(lines) and re.match(r'^\s*[^\[]*?(\d+)', lines[i + 1].strip()):
                next_line = lines[i + 1].strip()
                # 提取开头的数字
                start_number_match = re.match(r'^\s*[^\[]*?(\d+)', next_line)
                if start_number_match:
                    start_number = start_number_match.group(1)
                    # 构建合并后的行
                    merged_line = line[:-len(end_number)] + end_number + start_number
                    # 如果下一行还有其他内容，添加它
                    next_line_remainder = next_line[next_line.find(start_number) + len(start_number):]
                    if next_line_remainder:
                        merged_line += next_line_remainder
                    
                    print(f"修复跨行数据 - 行 {i+1}: 合并 {end_number} + {start_number} = {end_number+start_number}")
                    fixed_lines.append(merged_line)
                    fixed_count += 1
                    i += 2  # 跳过下一行
                    continue
        
        # 常规行，保持不变
        fixed_lines.append(line)
        i += 1
    
    print(f"找到并修复了 {fixed_count} 个跨行数据问题")
    
    # 用于存储解析后的数据
    data = []
    
    # 正则表达式模式
    timestamp_pattern = r'\[(\d{2}:\d{2}:\d{2}\.\d{3})\]'
    tpask1_pattern = r'\$TPASK,1,1\*'
    tpdat1_pattern = r'\$TPDAT,1,(\w+),(?:\d+,){4}(\d+),'
    tpask3_pattern = r'\$TPASK,3,1\*'
    tpdat3_pattern = r'\$TPDAT,3,(\w+),(\d+),(\d+),(\d+)'
    
    current_timestamp = None
    current_data = {}
    
    # 计数器，用于调试
    line_count = 0
    timestamp_matches = 0
    tpask1_matches = 0
    tpdat1_matches = 0
    tpask3_matches = 0
    tpdat3_matches = 0
    complete_records = 0
    
    # 处理每一行
    for line in fixed_lines:
        line_count += 1
        line = line.strip()
        if not line:
            continue
        
        # 提取时间戳
        timestamp_match = re.search(timestamp_pattern, line)
        if timestamp_match:
            timestamp_matches += 1
            line_timestamp = timestamp_match.group(1)
            
            # 检查TPASK,1请求
            if re.search(tpask1_pattern, line):
                tpask1_matches += 1
                current_timestamp = line_timestamp
                current_data = {'timestamp': current_timestamp}
            
            # 检查TPDAT,1响应
            tpdat1_match = re.search(tpdat1_pattern, line)
            if tpdat1_match and current_timestamp:
                tpdat1_matches += 1
                pressure1 = tpdat1_match.group(1)
                try:
                    temp1 = int(tpdat1_match.group(2))
                    # 保留原始十六进制压力值格式
                    current_data['pressure1'] = pressure1 
                    # 十六进制值作为字符串，不转换为十进制
                    current_data['pressure1_dec'] = pressure1
                    # 只有当温度值不是9966时才计算，并保留2位小数
                    if temp1 != 9966:
                        temp1_value = round(temp1/100 - 20, 2)
                        # 定义温度合理范围
                        MAX_TEMP = 50
                        # 只保存合理范围内的温度值
                        if 0 <= temp1_value <= MAX_TEMP:
                            current_data['temp1'] = temp1_value
                        else:
                            current_data['temp1'] = None
                            if temp1_value > MAX_TEMP:
                                print(f"警告：行 {line_count} 母节点1异常高温: {temp1_value}°C, 已过滤")
                    else:
                        current_data['temp1'] = None
                except Exception as e:
                    print(f"错误：解析TPDAT1失败: {e}, 行: {line}")
            
            # 检查TPASK,3请求
            if re.search(tpask3_pattern, line):
                tpask3_matches += 1
                # 只标记，不需要处理
            
            # 检查TPDAT,3响应
            tpdat3_match = re.search(tpdat3_pattern, line)
            if tpdat3_match and 'timestamp' in current_data:
                tpdat3_matches += 1
                try:
                    pressure2 = tpdat3_match.group(1)
                    node2_temp1 = int(tpdat3_match.group(2))
                    node2_temp2 = int(tpdat3_match.group(3))
                    node2_temp3 = int(tpdat3_match.group(4))
                    
                    # 保留原始十六进制压力值格式
                    current_data['pressure2'] = pressure2
                    # 十六进制值作为字符串，不转换为十进制
                    current_data['pressure2_dec'] = pressure2
                    
                    # 计算子节点和母节点温度，并保留2位小数，排除负值和异常高值
                    temp_child1 = round(node2_temp1/100 - 20, 2)
                    temp_node2 = round(node2_temp2/100 - 20, 2)
                    temp_child2 = round(node2_temp3/100 - 20, 2)
                    
                    # 定义温度合理范围（例如-20到50摄氏度）
                    MIN_TEMP = -20
                    MAX_TEMP = 50
                    
                    # 只保存合理范围内的温度值
                    current_data['child1_temp'] = temp_child1 if (temp_child1 >= 0 and temp_child1 <= MAX_TEMP) else None
                    current_data['node2_temp'] = temp_node2 if (temp_node2 >= 0 and temp_node2 <= MAX_TEMP) else None
                    current_data['child2_temp'] = temp_child2 if (temp_child2 >= 0 and temp_child2 <= MAX_TEMP) else None
                    
                    # 如果有异常温度值，记录日志
                    if temp_child1 > MAX_TEMP or temp_node2 > MAX_TEMP or temp_child2 > MAX_TEMP:
                        print(f"警告：行 {line_count} 检测到异常高温度值: 子节点1={temp_child1}°C, 母节点2={temp_node2}°C, 子节点2={temp_child2}°C，已过滤")
                    
                    # 检查子节点2温度是否为空，如果为空则排除整行数据
                    if current_data.get('child2_temp') is None:
                        print(f"警告：行 {line_count} 子节点2温度为空，已排除此行数据")
                        current_data = {}
                        current_timestamp = None
                        continue
                    
                    # 检查是否至少有一个正温度值
                    all_temps_negative = (
                        (current_data.get('temp1') is None) and
                        (current_data.get('child1_temp') is None) and
                        (current_data.get('node2_temp') is None) and
                        (current_data.get('child2_temp') is None)
                    )
                    
                    # 如果至少有一个温度值为正数，添加到数据列表
                    if not all_temps_negative and 'pressure1' in current_data:
                        # 格式化时间戳
                        timestamp_parts = current_data['timestamp'].split(':')
                        short_ts = f"{timestamp_parts[0]}:{timestamp_parts[1]}.{timestamp_parts[2].split('.')[1][:1]}"
                        current_data['short_timestamp'] = short_ts
                        
                        # 添加完整的datetime对象用于图表
                        current_data['datetime'] = datetime.strptime(current_data['timestamp'], '%H:%M:%S.%f')
                        
                        data.append(current_data.copy())
                        complete_records += 1
                    
                    # 重置当前数据
                    current_data = {}
                    current_timestamp = None
                    
                except Exception as e:
                    print(f"错误：解析TPDAT3失败: {e}, 行: {line}")
    
    # 打印调试统计信息
    print(f"\n--- 解析统计 ---")
    print(f"总行数: {line_count}")
    print(f"修复的跨行数据: {fixed_count}")
    print(f"时间戳匹配: {timestamp_matches}")
    print(f"TPASK,1匹配: {tpask1_matches}")
    print(f"TPDAT,1匹配: {tpdat1_matches}")
    print(f"TPASK,3匹配: {tpask3_matches}")
    print(f"TPDAT,3匹配: {tpdat3_matches}")
    print(f"完整记录数: {complete_records}")
    print(f"最终数据行数: {len(data)}")
    
    if len(data) == 0:
        print("警告：未能提取任何有效数据。请检查文件格式是否匹配期望的模式。")
    
    return data

def create_output_dir():
    """创建以当前时间命名的输出目录"""
    # 生成时间戳，格式为：年月日_时分秒
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    output_dir = f"output_{timestamp}"
    
    # 创建主输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # 创建charts子目录
    charts_dir = os.path.join(output_dir, "charts")
    if not os.path.exists(charts_dir):
        os.makedirs(charts_dir)
    
    return output_dir, charts_dir

def create_csv(data, output_dir):
    """将数据保存为CSV文件"""
    # 定义输出文件路径
    output_file = os.path.join(output_dir, "processed_data.csv")
    
    # 定义列名
    fieldnames = [
        '时间戳', '母节点1压力(kPa)', '母节点1温度', 
        '母节点2压力(kPa)', '子节点1温度', '母节点2温度', '子节点2温度'
    ]
    
    # 写入CSV文件
    with open(output_file, 'w', newline='', encoding='utf-8-sig') as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        writer.writeheader()
        
        for row in data:
            writer.writerow({
                '时间戳': row['short_timestamp'],
                '母节点1压力(kPa)': row['pressure1'],
                '母节点1温度': row['temp1'],
                '母节点2压力(kPa)': row['pressure2'],
                '子节点1温度': row['child1_temp'],
                '母节点2温度': row['node2_temp'],
                '子节点2温度': row['child2_temp']
            })
    
    print(f"数据已保存至 {output_file}")
    return output_file

def generate_html_chart(data, charts_dir):
    """生成HTML格式的图表，不依赖matplotlib"""
    
    # 获取当前日期，格式为：年-月-日
    current_date = datetime.now().strftime("%Y-%m-%d")
    
    # 准备数据
    timestamps = []
    temp_node1 = []
    temp_child1 = []
    temp_node2 = []
    temp_child2 = []
    pressure1 = []
    pressure2 = []
    
    for entry in data:
        ts = entry['short_timestamp']
        timestamps.append(ts)
        
        # 温度数据，None值用JavaScript的null表示，确保数值作为数值传递
        if entry['temp1'] is not None:
            temp_node1.append(entry['temp1'])
        else:
            temp_node1.append("null")
            
        if entry['child1_temp'] is not None:
            temp_child1.append(entry['child1_temp'])
        else:
            temp_child1.append("null")
            
        if entry['node2_temp'] is not None:
            temp_node2.append(entry['node2_temp'])
        else:
            temp_node2.append("null")
            
        if entry['child2_temp'] is not None:
            temp_child2.append(entry['child2_temp'])
        else:
            temp_child2.append("null")
        
        # 压力数据，提取十六进制字符串的实际值（去掉前导零）
        # 对于"0091"提取"91"并转为十进制91，对于"0107"提取"107"并转为十进制107
        pressure1.append(int(entry['pressure1_dec'].lstrip('0')))
        pressure2.append(int(entry['pressure2_dec'].lstrip('0')))
    
    # 时间戳需要作为字符串传递
    timestamp_json = json.dumps(timestamps)
    
    # 构建温度图表HTML，确保数值作为数值而非字符串
    temp_chart_html = f"""
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>温度随时间变化图</title>
        <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    </head>
    <body>
        <div style="width:90%; margin:0 auto;">
            <canvas id="tempChart"></canvas>
        </div>
        
        <script>
            const ctx = document.getElementById('tempChart');
            
            // 温度数据
            const tempData1 = [{','.join(['null' if x == "null" else str(x) for x in temp_node1])}];
            const tempData2 = [{','.join(['null' if x == "null" else str(x) for x in temp_child1])}];
            const tempData3 = [{','.join(['null' if x == "null" else str(x) for x in temp_node2])}];
            const tempData4 = [{','.join(['null' if x == "null" else str(x) for x in temp_child2])}];
            
            new Chart(ctx, {{
                type: 'line',
                data: {{
                    labels: {timestamp_json},
                    datasets: [
                        {{
                            label: '母节点1温度',
                            data: tempData1,
                            borderColor: 'red',
                            tension: 0.1
                        }},
                        {{
                            label: '子节点1温度',
                            data: tempData2,
                            borderColor: 'green',
                            tension: 0.1
                        }},
                        {{
                            label: '母节点2温度',
                            data: tempData3,
                            borderColor: 'blue',
                            tension: 0.1
                        }},
                        {{
                            label: '子节点2温度',
                            data: tempData4,
                            borderColor: 'orange',
                            tension: 0.1
                        }}
                    ]
                }},
                options: {{
                    responsive: true,
                    plugins: {{
                        title: {{
                            display: true,
                            text: '温度随时间变化图 ({current_date})',
                            font: {{
                                size: 16
                            }}
                        }}
                    }},
                    scales: {{
                        y: {{
                            title: {{
                                display: true,
                                text: '温度 (°C)'
                            }}
                        }},
                        x: {{
                            title: {{
                                display: true,
                                text: '时间'
                            }}
                        }}
                    }}
                }}
            }});
        </script>
    </body>
    </html>
    """
    
    # 构建压力图表HTML
    pressure_chart_html = f"""
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>压力随时间变化图</title>
        <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    </head>
    <body>
        <div style="width:90%; margin:0 auto;">
            <canvas id="pressureChart"></canvas>
        </div>
        
        <script>
            const ctx = document.getElementById('pressureChart');
            
            // 压力数据
            const pressureData1 = [{','.join([str(x) for x in pressure1])}];
            const pressureData2 = [{','.join([str(x) for x in pressure2])}];
            
            new Chart(ctx, {{
                type: 'line',
                data: {{
                    labels: {timestamp_json},
                    datasets: [
                        {{
                            label: '母节点1压力(kPa)',
                            data: pressureData1,
                            borderColor: 'red',
                            tension: 0.1
                        }},
                        {{
                            label: '母节点2压力(kPa)',
                            data: pressureData2,
                            borderColor: 'blue',
                            tension: 0.1
                        }}
                    ]
                }},
                options: {{
                    responsive: true,
                    plugins: {{
                        title: {{
                            display: true,
                            text: '压力随时间变化图 ({current_date})',
                            font: {{
                                size: 16
                            }}
                        }}
                    }},
                    scales: {{
                        y: {{
                            title: {{
                                display: true,
                                text: '压力值(kPa)'
                            }}
                        }},
                        x: {{
                            title: {{
                                display: true,
                                text: '时间'
                            }}
                        }}
                    }}
                }}
            }});
        </script>
    </body>
    </html>
    """
    
    # 写入HTML文件
    temp_chart_path = os.path.join(charts_dir, "temperature.html")
    with open(temp_chart_path, 'w', encoding='utf-8') as f:
        f.write(temp_chart_html)
    
    pressure_chart_path = os.path.join(charts_dir, "pressure.html")
    with open(pressure_chart_path, 'w', encoding='utf-8') as f:
        f.write(pressure_chart_html)
    
    print(f"HTML图表已保存至 {charts_dir} 目录：")
    print(f"  - 温度图表：{temp_chart_path}")
    print(f"  - 压力图表：{pressure_chart_path}")
    
    return temp_chart_path, pressure_chart_path

def main():
    # 自动检测当前目录中最新的TXT文件
    txt_files = glob.glob("*.TXT")
    
    # 过滤掉requirements.txt文件（如果被错误包含）
    txt_files = [f for f in txt_files if f.upper().endswith('.TXT') and f != 'requirements.txt']
    
    if not txt_files:
        # 如果没有找到TXT文件，使用默认文件名
        input_file = 'SaveWindows2025_4_3_16-30-28.TXT'
        print(f"未找到任何TXT文件，使用默认文件：{input_file}")
    else:
        # 按修改时间排序，获取最新的文件
        input_file = max(txt_files, key=os.path.getmtime)
        print(f"自动检测到最新文件：{input_file}")
        
    # 检查文件是否存在
    if not os.path.exists(input_file):
        print(f"错误：文件 {input_file} 不存在!")
        return
    
    # 显示文件大小信息
    file_size = os.path.getsize(input_file)
    print(f"文件大小: {file_size} 字节")
    
    # 创建以时间戳命名的输出目录
    output_dir, charts_dir = create_output_dir()
    
    # 解析日志文件
    print(f"\n开始解析文件 {input_file}...")
    data = parse_log_file(input_file)
    
    if not data:
        print("错误：无法从文件中提取有效数据，处理已终止。")
        return
    
    # 创建CSV文件
    print(f"\n正在创建CSV文件...")
    csv_file = create_csv(data, output_dir)
    
    # 生成HTML图表
    print(f"\n正在生成HTML图表...")
    try:
        temp_chart, pressure_chart = generate_html_chart(data, charts_dir)
    except Exception as e:
        print(f"生成图表时发生错误: {e}")
        print("您可以使用Excel或其他工具打开CSV文件手动创建图表。")
    
    print(f"\n处理完成。共处理 {len(data)} 条数据记录。")
    print(f"所有输出文件已保存在 {output_dir} 目录。")
    
    # 输出一些数据统计信息
    if len(data) > 0:
        print("\n--- 数据统计 ---")
        # 温度数据统计
        temp_values = [entry['temp1'] for entry in data if entry.get('temp1') is not None]
        child1_temps = [entry['child1_temp'] for entry in data if entry.get('child1_temp') is not None]
        node2_temps = [entry['node2_temp'] for entry in data if entry.get('node2_temp') is not None]
        child2_temps = [entry['child2_temp'] for entry in data if entry.get('child2_temp') is not None]
        
        if temp_values:
            print(f"母节点1温度: 最小值={min(temp_values):.2f}°C, 最大值={max(temp_values):.2f}°C, 平均值={(sum(temp_values)/len(temp_values)):.2f}°C")
        if child1_temps:
            print(f"子节点1温度: 最小值={min(child1_temps):.2f}°C, 最大值={max(child1_temps):.2f}°C, 平均值={(sum(child1_temps)/len(child1_temps)):.2f}°C")
        if node2_temps:
            print(f"母节点2温度: 最小值={min(node2_temps):.2f}°C, 最大值={max(node2_temps):.2f}°C, 平均值={(sum(node2_temps)/len(node2_temps)):.2f}°C")
        if child2_temps:
            print(f"子节点2温度: 最小值={min(child2_temps):.2f}°C, 最大值={max(child2_temps):.2f}°C, 平均值={(sum(child2_temps)/len(child2_temps)):.2f}°C")
        
        # 压力数据统计，去掉前导零并转为十进制
        pressure1_dec = [int(entry['pressure1_dec'].lstrip('0')) for entry in data]
        pressure2_dec = [int(entry['pressure2_dec'].lstrip('0')) for entry in data]
        
        print(f"母节点1压力: 最小值={min(pressure1_dec)} kPa, 最大值={max(pressure1_dec)} kPa, 平均值={(sum(pressure1_dec)/len(pressure1_dec)):.2f} kPa")
        print(f"母节点2压力: 最小值={min(pressure2_dec)} kPa, 最大值={max(pressure2_dec)} kPa, 平均值={(sum(pressure2_dec)/len(pressure2_dec)):.2f} kPa")
        
    print("\n请用浏览器打开以下文件查看温度和压力图表：")
    print(f"1. 温度图表: {os.path.join(output_dir, 'charts', 'temperature.html')}")
    print(f"2. 压力图表: {os.path.join(output_dir, 'charts', 'pressure.html')}")
    print(f"3. 数据表格: {os.path.join(output_dir, 'processed_data.csv')}")

if __name__ == "__main__":
    main() 